package com.coszero.utils.decoration

import android.content.Context
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.view.View
import androidx.annotation.DimenRes
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager

/**
 * 横线分割线
 *
 * @author xmqian
 * Created by yqritc on 2015/01/15.
 * @version 1
 */
class HorizontalDividerItemDecoration protected constructor(builder: Builder) :
    FlexibleDividerDecoration(builder) {
    private val mMarginProvider: MarginProvider

    init {
        mMarginProvider = builder.mMarginProvider
    }

    override fun getDividerBound(position: Int, parent: RecyclerView, child: View): Rect {
        val bounds: Rect = Rect(0, 0, 0, 0)
        val transitionX: Int = ViewCompat.getTranslationX(child).toInt()
        val transitionY: Int = ViewCompat.getTranslationY(child).toInt()
        val params: RecyclerView.LayoutParams = child.getLayoutParams() as RecyclerView.LayoutParams
        bounds.left = child.getLeft() + transitionX
        bounds.right = child.getRight() + transitionX

        val dividerSize: Int = getDividerSize(position, parent)
        if (mDividerType == DividerType.DRAWABLE || mDividerType == DividerType.SPACE) {
            if (alignLeftEdge(parent, position)) {
                bounds.left += mMarginProvider.dividerLeftMargin(position, parent)
            }

            if (alignRightEdge(parent, position)) {
                bounds.right -= mMarginProvider.dividerRightMargin(position, parent)
            } else {
                // 交叉位置特殊处理
                bounds.right += getDividerSize(position, parent)
            }
            bounds.top = child.getBottom() + params.bottomMargin + transitionY
            bounds.bottom = bounds.top + dividerSize
        } else {
            val halfSize: Int = dividerSize / 2
            bounds.top = child.getBottom() + params.bottomMargin + halfSize + transitionY
            bounds.bottom = bounds.top
        }

        if (mPositionInsideItem) {
            bounds.top -= dividerSize
            bounds.bottom -= dividerSize
        }

        return bounds
    }

    private fun alignLeftEdge(parent: RecyclerView, position: Int): Boolean {
        val layoutManager: RecyclerView.LayoutManager? = parent.getLayoutManager()

        if (layoutManager is GridLayoutManager) {
            val manager: GridLayoutManager = layoutManager
            val lookup: SpanSizeLookup = manager.getSpanSizeLookup()
            val spanCount: Int = manager.getSpanCount()
            if (manager.getOrientation() == GridLayoutManager.VERTICAL)  // 垂直布局
            {
                if (lookup.getSpanIndex(position, spanCount) == 0)  // 第一列
                {
                    return true
                }
            } else  // 水平布局
            {
                if (manager.getReverseLayout()) {
                    return lookup.getSpanGroupIndex(
                        position,
                        spanCount
                    ) == lookup.getSpanGroupIndex(
                        parent.getAdapter()!!.getItemCount() - 1, spanCount
                    )
                } else {
                    if (lookup.getSpanGroupIndex(position, spanCount) == 0) {
                        return true
                    }
                }
            }
        } else if (layoutManager is StaggeredGridLayoutManager) {
            val manager: StaggeredGridLayoutManager = layoutManager
            val params: StaggeredGridLayoutManager.LayoutParams = manager.findViewByPosition(
                position
            )!!
                .getLayoutParams() as StaggeredGridLayoutManager.LayoutParams
            val spanCount: Int = manager.getSpanCount()
            val spanIndex: Int = params.getSpanIndex()

            if (manager.getOrientation() == StaggeredGridLayoutManager.VERTICAL)  // 垂直布局
            {
                return spanIndex == 0
            } else  // 水平布局
            {
                if (manager.getReverseLayout()) {
                    val lastPosition: IntArray = manager.findLastVisibleItemPositions(null)
                    var hasDirectionAlign: Boolean = false
                    for (p: Int in lastPosition) {
                        if (p != position && p != -1) {
                            val params1: StaggeredGridLayoutManager.LayoutParams =
                                manager.findViewByPosition(
                                    p
                                )!!
                                    .getLayoutParams() as StaggeredGridLayoutManager.LayoutParams
                            if (params1.getSpanIndex() == spanIndex) {
                                hasDirectionAlign = true
                                break
                            }
                        }
                    }
                    return !hasDirectionAlign
                } else {
                    return position < spanCount
                }
            }
        } else if (layoutManager is LinearLayoutManager) {
            return true
        }
        return false
    }

    private fun alignRightEdge(parent: RecyclerView, position: Int): Boolean {
        val layoutManager: RecyclerView.LayoutManager? = parent.getLayoutManager()

        if (layoutManager is GridLayoutManager) {
            val manager: GridLayoutManager = layoutManager
            val lookup: SpanSizeLookup = manager.getSpanSizeLookup()
            val spanCount: Int = manager.getSpanCount()
            val itemCount: Int = parent.getAdapter()!!.getItemCount()
            if (manager.getOrientation() == GridLayoutManager.VERTICAL)  // 垂直布局
            {
                if (positionTotalSpanSize(manager, position) == spanCount) {
                    return true
                }
            } else  // 水平布局
            {
                if (manager.getReverseLayout()) {
                    return lookup.getSpanGroupIndex(position, spanCount) == 0
                } else {
                    var lastRowFirstPosition: Int = 0
                    for (i in itemCount - 1 downTo 0) {
                        if (lookup.getSpanIndex(i, spanCount) == 0) {
                            lastRowFirstPosition = i
                            break
                        }
                    }
                    if (position >= lastRowFirstPosition) {
                        return true
                    }
                }
            }
        } else if (layoutManager is StaggeredGridLayoutManager) {
            val manager: StaggeredGridLayoutManager = layoutManager
            val params: StaggeredGridLayoutManager.LayoutParams = manager.findViewByPosition(
                position
            )!!
                .getLayoutParams() as StaggeredGridLayoutManager.LayoutParams
            val spanCount: Int = manager.getSpanCount()
            val spanIndex: Int = params.getSpanIndex()

            if (manager.getOrientation() == StaggeredGridLayoutManager.VERTICAL)  // 垂直布局
            {
                return spanIndex == spanCount - 1
            } else  // 水平布局
            {
                if (manager.getReverseLayout()) {
                    return position < spanCount
                } else {
                    val lastPosition: IntArray = manager.findLastVisibleItemPositions(null)

                    var hasRight: Boolean = false
                    for (p: Int in lastPosition) {
                        if (p != position && p != -1) {
                            val params1: StaggeredGridLayoutManager.LayoutParams =
                                manager.findViewByPosition(
                                    p
                                )!!
                                    .getLayoutParams() as StaggeredGridLayoutManager.LayoutParams
                            if (params1.getSpanIndex() == spanIndex) {
                                hasRight = true
                                break
                            }
                        }
                    }
                    return !hasRight
                }
            }
        } else if (layoutManager is LinearLayoutManager) {
            return true
        }
        return false
    }

    override fun setItemOffsets(outRect: Rect, position: Int, parent: RecyclerView) {
        if (mPositionInsideItem) {
            outRect.set(0, 0, 0, 0)
            return
        }
        outRect.set(0, 0, 0, getDividerSize(position, parent))
    }

    private fun getDividerSize(position: Int, parent: RecyclerView): Int {
        if (mPaintProvider != null) {
            return mPaintProvider!!.dividerPaint(position, parent).getStrokeWidth().toInt()
        } else if (mSizeProvider != null) {
            return mSizeProvider!!.dividerSize(position, parent)
        } else if (mDrawableProvider != null) {
            val drawable: Drawable? = mDrawableProvider!!.drawableProvider(position, parent)
            return drawable!!.getIntrinsicHeight()
        } else if (mSpaceProvider != null) {
            return mSpaceProvider!!.dividerSize(position, parent)
        }
        throw RuntimeException("failed to get size")
    }

    /**
     * Interface for controlling divider margin
     */
    interface MarginProvider {
        /**
         * Returns left margin of divider.
         *
         * @param position Divider position (or group index for GridLayoutManager)
         * @param parent RecyclerView
         * @return left margin
         */
        fun dividerLeftMargin(position: Int, parent: RecyclerView?): Int

        /**
         * Returns right margin of divider.
         *
         * @param position Divider position (or group index for GridLayoutManager)
         * @param parent RecyclerView
         * @return right margin
         */
        fun dividerRightMargin(position: Int, parent: RecyclerView?): Int
    }

    class Builder(context: Context) :
        FlexibleDividerDecoration.Builder<Builder?>(context) {
        var mMarginProvider: MarginProvider = object : MarginProvider {
            override fun dividerLeftMargin(position: Int, parent: RecyclerView?): Int {
                return 0
            }

            override fun dividerRightMargin(position: Int, parent: RecyclerView?): Int {
                return 0
            }
        }

        fun margin(leftMargin: Int, rightMargin: Int): Builder {
            return marginProvider(object : MarginProvider {
                override fun dividerLeftMargin(position: Int, parent: RecyclerView?): Int {
                    return leftMargin
                }

                override fun dividerRightMargin(position: Int, parent: RecyclerView?): Int {
                    return rightMargin
                }
            })
        }

        fun margin(horizontalMargin: Int): Builder {
            return margin(horizontalMargin, horizontalMargin)
        }

        fun marginResId(@DimenRes leftMarginId: Int, @DimenRes rightMarginId: Int): Builder {
            return margin(
                mResources.getDimensionPixelSize(leftMarginId),
                mResources.getDimensionPixelSize(rightMarginId)
            )
        }

        fun marginResId(@DimenRes horizontalMarginId: Int): Builder {
            return marginResId(horizontalMarginId, horizontalMarginId)
        }

        fun marginProvider(provider: MarginProvider): Builder {
            mMarginProvider = provider
            return this
        }

        fun build(): HorizontalDividerItemDecoration {
            checkBuilderParams()
            return HorizontalDividerItemDecoration(this)
        }
    }
}